"""

爬取在线书店http://books.toscrape.com/的所有信息，包括图书的名字、封面图片、价格、评分、库存、产品介绍、所属分类。

"""

import requests
from lxml import etree
import re

headers = {'User-Agent': 'Mozilla/5.0'}
BookStore = []


class Book:
    def __init__(self, name, pic, price, score, stock, info, category):
        self.name = name
        self.pic = pic
        self.price = price
        self.score = score
        self.stock = stock
        self.info = info
        self.category = category

    def prtInfo(self):
        print("名称： ", self.name, '图片地址：', self.pic, '价格：', self.price, '评分：', self.score, '产品介绍：', self.info, "所属分类：",
              self.category, sep='\n')


def parseBookDetail(link, imagePath):
    url = link
    res = requests.get(url=url, headers=headers, verify=False)
    res.encoding = "utf-8"
    html = res.text
    prase_html = etree.HTML(html)

    # 定位到详细信息
    details = prase_html.xpath(
        "//div[@id='content_inner']/article[@class='product_page']/div[@class='row']/div[@class='col-sm-6 product_main']")
    # 获取详细信息
    if len(details) > 0:
        details = details[0]
        name = details.xpath("./h1/text()")
        if len(name) > 0:
            name = name[0]
        else:
            name = None
        price = details.xpath("./p[@class='price_color']/text()")
        if len(price) > 0:
            price = price[0]
        else:
            price = None

        # 获取p标签的class 对应的分数
        score = None
        ps = details.xpath("./p")
        for p in ps:
            if len(p.xpath("./@class")) > 0 and 'star-rating' in p.xpath("./@class")[0]:
                score = str(p.xpath("./@class")[0]).split(' ')[-1]

        # 用正则匹配库存
        stock_detail = details.xpath("./p[@class='instock availability']/text()")
        if len(stock_detail) > 0:
            # 正则匹配需要去掉换行符
            stock_detail = stock_detail[0].replace("\n", "").replace("\r", "")
            rx = re.compile(r'\d')
            num = rx.findall(stock_detail)
            if len(num) > 0:
                stock = num[0]
            else:
                stock = 0
        else:
            stock = 0

        info = prase_html.xpath("//div[@id='content_inner']/article[@class='product_page']/p/text()")
        if len(info) > 0:
            info = info[0]
        else:
            info = None

        category = None
        trs = prase_html.xpath("//div[@id='content_inner']/article[@class='product_page']/table/tr")
        for tr in trs:
            if len(tr.xpath("./th")) > 0 and 'Type' in tr.xpath("./th/text()")[0] and len(tr.xpath("./td/text()")) > 0:
                category = tr.xpath("./td/text()")[0]

        book = Book(name, imagePath, price, score, stock, info, category)
        BookStore.append(book)
        print('add a new book to BookStore: ', name, imagePath, price, score, stock, info, category)


if __name__ == '__main__':
    for i in range(1, 51):
        url = 'http://books.toscrape.com/catalogue/page-' + str(i) + '.html'
        res = requests.get(url=url, headers=headers, verify=False)
        res.encoding = "gb2312"
        html = res.text
        parse_html = etree.HTML(html)

        books = parse_html.xpath("//ol[@class='row']/li")
        for book in books:
            link = book.xpath("./article[@class='product_pod']/div[@class='image_container']/a/@href")
            if len(link) > 0:
                link = 'http://books.toscrape.com/catalogue/' + link[0]
                image_path = book.xpath("./article[@class='product_pod']/div[@class='image_container']/a/img/@src")
                if len(image_path) > 0:
                    image_path = 'http://books.toscrape.com/' + image_path[0][3:]
                else:
                    image_path = None
                parseBookDetail(link, image_path)
            else:
                continue
    for book in BookStore:
        book.prtInfo()
